#  新增的基本运用

import open3d as o3d
import numpy as np

# Part1 里的点云读取
ply_point_cloud = o3d.data.PLYPointCloud()
pcd = o3d.io.read_point_cloud(ply_point_cloud.path)
print(pcd)
print(np.asarray(pcd.points))

# Part2 里的体素下采样
print("Downsample the point cloud with a voxel of 0.05")
downpcd = pcd.voxel_down_sample(voxel_size = 0.05)

# 这块是新增的法向量估计
print("Recompute the normal of the downsampled point cloud")
# estimate_normals 是 geometry.PointCloud 类的实例方法，专门用于为点云计算每个点的法向
# search_param 参数用于配置 邻域点的搜索规则
#                              领域搜索规则？这就又要回到最开始的  顶点法向估计是怎么进行的？
#      geometry.KDTreeSearchParamHybrid 是混合搜索策略  底层还是基于KDTree（这块先不讲，之后有机会再深入研究研究这个算法）
#                    radius 设定 邻域搜索半径   示例中的 radius=0.1 表示只找 距离当前点小于 0.1 的点作为 邻域点
#                    max_nn 设定 每个点最多找 多少 个邻域点 示例中的 max_nn=30 表示找领域范围内最近的30个点
# downpcd.estimate_normals(
#     search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.1, max_nn=30))

# 可以试着修改一下参数
# radius = 0.5
# max_nn = 30
# 缩小范围
# radius = 0.1
# max_nn = 3
# 扩大范围
radius = 1
max_nn = 100
downpcd.estimate_normals(
    search_param=o3d.geometry.KDTreeSearchParamHybrid(radius, max_nn))
# 实际发现，领域或者最大可取点数太小时，法向不稳定，局部性太强


# 显示新增的一个参数
# point_show_normal 控制是否显示点云的法线  当它等于True时，显示法线；为False时，不显示
o3d.visualization.draw_geometries([downpcd],
                                  zoom=0.3412,
                                  front=[0.4257, -0.2125, -0.8795],
                                  lookat=[2.6172, 2.0475, 1.532],
                                  up=[-0.0694, -0.9768, 0.2024],
                                  point_show_normal=True)
# 关闭point_show_normal后法向消失